﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Core.Net;
using HslCommunication.LogNet;
using HslCommunication.Reflection;
using Newtonsoft.Json.Linq;

namespace HslCommunication.MQTT
{
	/// <summary>
	/// 一个Mqtt的服务器类对象，本服务器支持发布订阅操作，支持从服务器强制推送数据，支持往指定的客户端推送，支持基于一问一答的远程过程调用（RPC）的数据交互，支持文件上传下载。根据这些功能从而定制化出满足各个场景的服务器，详细的使用说明可以参见代码api文档示例。<br />
	/// An Mqtt server class object. This server supports publish and subscribe operations, supports forced push data from the server, 
	/// supports push to designated clients, supports data interaction based on one-question-one-answer remote procedure calls (RPC), 
	/// and supports file upload and download . According to these functions, the server can be customized to meet various scenarios. 
	/// For detailed instructions, please refer to the code api document example.
	/// </summary>
	/// <remarks>
	/// 本MQTT服务器功能丰富，可以同时实现，用户名密码验证，在线客户端的管理，数据订阅推送，单纯的数据收发，心跳检测，同步数据访问，文件上传，下载，删除，遍历，详细参照下面的示例说明
	/// </remarks>
	/// <example>
	/// 最简单的使用，就是实例化，启动服务即可
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample1" title="简单的实例化" />
	/// 当然了，我们可以稍微的复杂一点，加一个功能，验证连接的客户端操作
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample2" title="增加验证" />
	/// 我们可以对ClientID，用户名，密码进行验证，那么我们可以动态修改client id么？比如用户名密码验证成功后，client ID我想设置为权限等级。
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample2_1" title="动态修改Client ID" />
	/// 如果我想强制该客户端不能主动发布主题，可以这么操作。
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample2_2" title="禁止发布主题" />
	/// 你也可以对clientid进行过滤验证，只要结果返回不是0，就可以了。接下来我们实现一个功能，所有客户端的发布的消息在控制台打印出来,
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample3" title="打印所有发布" />
	/// 捕获客户端刚刚上线的时候，方便我们进行一些额外的操作信息。下面的意思就是返回一个数据，将数据发送到指定的会话内容上去
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample4" title="客户端上线信息" />
	/// 下面演示如何从服务器端发布数据信息，包括多种发布的方法，消息是否驻留，详细看说明即可
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample5" title="服务器发布" />
	/// 下面演示如何支持同步网络访问，当客户端是同步网络访问时，协议内容会变成HUSL，即被视为同步客户端，进行相关的操作，主要进行远程调用RPC，以及查询MQTT的主题列表。
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample6" title="同步访问支持" />
	/// 如果需要查看在线信息，可以随时获取<see cref="P:HslCommunication.MQTT.MqttServer.OnlineCount" />属性，如果需要查看报文信息，可以实例化日志，参考日志的说明即可。<br /><br />
	/// 针对上面同步网络访问，虽然比较灵活，但是什么都要自己控制，无疑增加了代码的复杂度，举个例子，当你的topic分类很多的时候，已经客户端协议多个参数的时候，需要大量的手动解析的代码，
	/// 影响代码美观，而且让代码更加的杂乱，除此之外，还有个巨大的麻烦，服务器提供了很多的topic处理程序（可以换个称呼，暴露的API接口），
	/// 客户端没法清晰的浏览到，需要查找服务器代码才能知晓，而且服务器更新了接口，客户端有需要同步查看服务器的代码才行，以及做权限控制也很麻烦。<br />
	/// 所以在Hsl里面的MQTT服务器，提供了注册API接口的功能，只需要一行注册代码，你的类的方法自动就会变为API解析，所有的参数都是同步解析的，如果你返回的是
	/// OperateResult&lt;T&gt;类型对象，还支持是否成功的结果报告，否则一律视为json字符串，返回给调用方。
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample7" title="基于MQTT的RPC接口实现" />
	/// 如果需要查看在线信息，可以随时获取<see cref="P:HslCommunication.MQTT.MqttServer.OnlineCount" />属性，如果需要查看报文信息，可以实例化日志，参考日志的说明即可。<br /><br />
	/// 最后介绍一下文件管理服务是如何启动的，在启动了文件管理服务之后，其匹配的客户端 <see cref="T:HslCommunication.MQTT.MqttSyncClient" /> 就可以上传下载，遍历文件了。
	/// 而服务器端做的就是启用服务，如果你需要一些更加自由的权限控制，比如某个账户只能下载，不能其他操作，都是可以实现的。更加多的示例参考DEMO程序。
	/// <code lang="cs" source="HslCommunication_Net45.Test\Documentation\Samples\MQTT\MqttServerSample.cs" region="Sample8" title="基于MQTT的文件管理服务启动" />
	/// </example>
	// Token: 0x020000C6 RID: 198
	public class MqttServer : NetworkServerBase
	{
		/// <summary>
		/// 实例化一个MQTT协议的服务器<br />
		/// Instantiate a MQTT protocol server
		/// </summary>
		// Token: 0x06000E76 RID: 3702 RVA: 0x00055208 File Offset: 0x00053408
		public MqttServer()
		{
			this.statisticsDict = new LogStatisticsDict(GenerateMode.ByEveryDay, 60);
			this.retainKeys = new Dictionary<string, MqttClientApplicationMessage>();
			this.apiTopicServiceDict = new Dictionary<string, MqttRpcApiInfo>();
			this.keysLock = new object();
			this.rpcApiLock = new object();
			this.timerHeart = new Timer(new TimerCallback(this.ThreadTimerHeartCheck), null, 2000, 10000);
			this.dictionaryFilesMarks = new Dictionary<string, FileMarkId>();
			this.dictHybirdLock = new object();
		}

		/// <inheritdoc />
		// Token: 0x06000E77 RID: 3703 RVA: 0x000552D4 File Offset: 0x000534D4
		[DebuggerStepThrough]
		protected override void ThreadPoolLogin(Socket socket, IPEndPoint endPoint)
		{
			MqttServer.<ThreadPoolLogin>d__1 <ThreadPoolLogin>d__ = new MqttServer.<ThreadPoolLogin>d__1();
			<ThreadPoolLogin>d__.<>t__builder = AsyncVoidMethodBuilder.Create();
			<ThreadPoolLogin>d__.<>4__this = this;
			<ThreadPoolLogin>d__.socket = socket;
			<ThreadPoolLogin>d__.endPoint = endPoint;
			<ThreadPoolLogin>d__.<>1__state = -1;
			<ThreadPoolLogin>d__.<>t__builder.Start<MqttServer.<ThreadPoolLogin>d__1>(ref <ThreadPoolLogin>d__);
		}

		// Token: 0x06000E78 RID: 3704 RVA: 0x0005531C File Offset: 0x0005351C
		[DebuggerStepThrough]
		private void SocketReceiveCallback(IAsyncResult ar)
		{
			MqttServer.<SocketReceiveCallback>d__2 <SocketReceiveCallback>d__ = new MqttServer.<SocketReceiveCallback>d__2();
			<SocketReceiveCallback>d__.<>t__builder = AsyncVoidMethodBuilder.Create();
			<SocketReceiveCallback>d__.<>4__this = this;
			<SocketReceiveCallback>d__.ar = ar;
			<SocketReceiveCallback>d__.<>1__state = -1;
			<SocketReceiveCallback>d__.<>t__builder.Start<MqttServer.<SocketReceiveCallback>d__2>(ref <SocketReceiveCallback>d__);
		}

		// Token: 0x06000E79 RID: 3705 RVA: 0x0005535C File Offset: 0x0005355C
		private void SyncMqttReceiveProgressBack(Socket socket, long already, long total)
		{
			string message = (total > 0L) ? (already * 100L / total).ToString() : "100";
			byte[] array = new byte[16];
			BitConverter.GetBytes(already).CopyTo(array, 0);
			BitConverter.GetBytes(total).CopyTo(array, 8);
			base.Send(socket, MqttHelper.BuildMqttCommand(15, 0, MqttHelper.BuildSegCommandByString(message), array).Content);
		}

		// Token: 0x06000E7A RID: 3706 RVA: 0x000553C8 File Offset: 0x000535C8
		private void HandleMqttConnection(Socket socket, IPEndPoint endPoint, OperateResult<byte, byte[]> readMqtt)
		{
			bool flag = !readMqtt.IsSuccess;
			if (!flag)
			{
				OperateResult<int, MqttSession> operateResult = this.CheckMqttConnection(readMqtt.Content1, readMqtt.Content2, socket, endPoint);
				bool flag2 = !operateResult.IsSuccess;
				if (flag2)
				{
					ILogNet logNet = base.LogNet;
					if (logNet != null)
					{
						logNet.WriteInfo(this.ToString(), operateResult.Message);
					}
					if (socket != null)
					{
						socket.Close();
					}
				}
				else
				{
					bool flag3 = operateResult.Content1 != 0;
					if (flag3)
					{
						base.Send(socket, MqttHelper.BuildMqttCommand(2, 0, null, new byte[]
						{
							0,
							(byte)operateResult.Content1
						}).Content);
						if (socket != null)
						{
							socket.Close();
						}
					}
					else
					{
						base.Send(socket, MqttHelper.BuildMqttCommand(2, 0, null, new byte[2]).Content);
						try
						{
							socket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(this.SocketReceiveCallback), operateResult.Content2);
							this.AddMqttSession(operateResult.Content2);
						}
						catch (Exception ex)
						{
							ILogNet logNet2 = base.LogNet;
							if (logNet2 != null)
							{
								logNet2.WriteDebug(this.ToString(), "Client Online Exception : " + ex.Message);
							}
							return;
						}
						bool flag4 = operateResult.Content2.Protocol == "MQTT";
						if (flag4)
						{
							MqttServer.OnClientConnectedDelegate onClientConnected = this.OnClientConnected;
							if (onClientConnected != null)
							{
								onClientConnected(operateResult.Content2);
							}
						}
					}
				}
			}
		}

		// Token: 0x06000E7B RID: 3707 RVA: 0x00055540 File Offset: 0x00053740
		private OperateResult<int, MqttSession> CheckMqttConnection(byte mqttCode, byte[] content, Socket socket, IPEndPoint endPoint)
		{
			bool flag = mqttCode >> 4 != 1;
			OperateResult<int, MqttSession> result;
			if (flag)
			{
				result = new OperateResult<int, MqttSession>("Client Send Faied, And Close!");
			}
			else
			{
				bool flag2 = content.Length < 10;
				if (flag2)
				{
					result = new OperateResult<int, MqttSession>("Receive Data Too Short:" + SoftBasic.ByteToHexString(content, ' '));
				}
				else
				{
					string @string = Encoding.ASCII.GetString(content, 2, 4);
					bool flag3 = !(@string == "MQTT") && !(@string == "HUSL") && !(@string == "FILE");
					if (flag3)
					{
						result = new OperateResult<int, MqttSession>("Not Mqtt Client Connection");
					}
					else
					{
						try
						{
							int num = 10;
							string clientId = MqttHelper.ExtraMsgFromBytes(content, ref num);
							string text = ((content[7] & 4) == 4) ? MqttHelper.ExtraMsgFromBytes(content, ref num) : string.Empty;
							string text2 = ((content[7] & 4) == 4) ? MqttHelper.ExtraMsgFromBytes(content, ref num) : string.Empty;
							string userName = ((content[7] & 128) == 128) ? MqttHelper.ExtraMsgFromBytes(content, ref num) : string.Empty;
							string passwrod = ((content[7] & 64) == 64) ? MqttHelper.ExtraMsgFromBytes(content, ref num) : string.Empty;
							int num2 = (int)content[8] * 256 + (int)content[9];
							MqttSession mqttSession = new MqttSession(endPoint, @string)
							{
								MqttSocket = socket,
								ClientId = clientId,
								UserName = userName
							};
							int value = (this.ClientVerification != null) ? this.ClientVerification(mqttSession, clientId, userName, passwrod) : 0;
							bool flag4 = num2 > 0;
							if (flag4)
							{
								mqttSession.ActiveTimeSpan = TimeSpan.FromSeconds((double)num2);
							}
							result = OperateResult.CreateSuccessResult<int, MqttSession>(value, mqttSession);
						}
						catch (Exception ex)
						{
							result = new OperateResult<int, MqttSession>("Client Online Exception : " + ex.Message);
						}
					}
				}
			}
			return result;
		}

		// Token: 0x06000E7C RID: 3708 RVA: 0x00055708 File Offset: 0x00053908
		private void HandleWithReceiveMqtt(MqttSession mqttSession, OperateResult<byte, byte[]> readMqtt)
		{
			bool flag = !readMqtt.IsSuccess;
			if (flag)
			{
				this.RemoveAndCloseSession(mqttSession, readMqtt.Message);
			}
			else
			{
				byte content = readMqtt.Content1;
				byte[] content2 = readMqtt.Content2;
				try
				{
					bool flag2 = content >> 4 != 14;
					if (!flag2)
					{
						this.RemoveAndCloseSession(mqttSession, string.Empty);
						return;
					}
					mqttSession.MqttSocket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(this.SocketReceiveCallback), mqttSession);
				}
				catch (Exception ex)
				{
					this.RemoveAndCloseSession(mqttSession, "HandleWithReceiveMqtt:" + ex.Message);
					return;
				}
				mqttSession.ActiveTime = DateTime.Now;
				bool flag3 = mqttSession.Protocol != "MQTT";
				if (flag3)
				{
					this.DealWithPublish(mqttSession, content, content2);
				}
				else
				{
					bool flag4 = content >> 4 == 3;
					if (flag4)
					{
						this.DealWithPublish(mqttSession, content, content2);
					}
					else
					{
						bool flag5 = content >> 4 == 4;
						if (!flag5)
						{
							bool flag6 = content >> 4 == 5;
							if (!flag6)
							{
								bool flag7 = content >> 4 == 6;
								if (flag7)
								{
									base.Send(mqttSession.MqttSocket, MqttHelper.BuildMqttCommand(7, 0, null, content2).Content);
								}
								else
								{
									bool flag8 = content >> 4 == 8;
									if (flag8)
									{
										this.DealWithSubscribe(mqttSession, content, content2);
									}
									else
									{
										bool flag9 = content >> 4 == 10;
										if (flag9)
										{
											this.DealWithUnSubscribe(mqttSession, content, content2);
										}
										else
										{
											bool flag10 = content >> 4 == 12;
											if (flag10)
											{
												base.Send(mqttSession.MqttSocket, MqttHelper.BuildMqttCommand(13, 0, null, null).Content);
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		/// <inheritdoc />
		// Token: 0x06000E7D RID: 3709 RVA: 0x00009AA1 File Offset: 0x00007CA1
		protected override void StartInitialization()
		{
		}

		/// <inheritdoc />
		// Token: 0x06000E7E RID: 3710 RVA: 0x000558B8 File Offset: 0x00053AB8
		protected override void CloseAction()
		{
			base.CloseAction();
			object obj = this.sessionsLock;
			lock (obj)
			{
				for (int i = 0; i < this.mqttSessions.Count; i++)
				{
					Socket mqttSocket = this.mqttSessions[i].MqttSocket;
					if (mqttSocket != null)
					{
						mqttSocket.Close();
					}
				}
				this.mqttSessions.Clear();
			}
		}

		// Token: 0x06000E7F RID: 3711 RVA: 0x00055944 File Offset: 0x00053B44
		private void ThreadTimerHeartCheck(object obj)
		{
			MqttSession[] array = null;
			object obj2 = this.sessionsLock;
			lock (obj2)
			{
				array = this.mqttSessions.ToArray();
			}
			bool flag2 = array != null && array.Length != 0;
			if (flag2)
			{
				for (int i = 0; i < array.Length; i++)
				{
					bool flag3 = array[i].Protocol == "MQTT" && DateTime.Now - array[i].ActiveTime > array[i].ActiveTimeSpan;
					if (flag3)
					{
						this.RemoveAndCloseSession(array[i], "Thread Timer Heart Check failed:" + SoftBasic.GetTimeSpanDescription(DateTime.Now - array[i].ActiveTime));
					}
				}
			}
		}

		// Token: 0x06000E80 RID: 3712 RVA: 0x00055A30 File Offset: 0x00053C30
		private void DealWithPublish(MqttSession session, byte code, byte[] data)
		{
			bool flag = (code & 8) == 8;
			int num = (((code & 4) == 4) ? 2 : 0) + (((code & 2) == 2) ? 1 : 0);
			MqttQualityOfServiceLevel mqttQualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce;
			bool flag2 = num == 1;
			if (flag2)
			{
				mqttQualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce;
			}
			else
			{
				bool flag3 = num == 2;
				if (flag3)
				{
					mqttQualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce;
				}
				else
				{
					bool flag4 = num == 3;
					if (flag4)
					{
						mqttQualityOfServiceLevel = MqttQualityOfServiceLevel.OnlyTransfer;
					}
				}
			}
			bool flag5 = (code & 1) == 1;
			int data2 = 0;
			int length = 0;
			string topic = MqttHelper.ExtraMsgFromBytes(data, ref length);
			bool flag6 = num > 0;
			if (flag6)
			{
				data2 = MqttHelper.ExtraIntFromBytes(data, ref length);
			}
			byte[] payload = SoftBasic.ArrayRemoveBegin<byte>(data, length);
			MqttClientApplicationMessage mqttClientApplicationMessage = new MqttClientApplicationMessage
			{
				ClientId = session.ClientId,
				QualityOfServiceLevel = mqttQualityOfServiceLevel,
				Retain = flag5,
				Topic = topic,
				UserName = session.UserName,
				Payload = payload
			};
			bool flag7 = session.Protocol == "MQTT";
			if (flag7)
			{
				bool flag8 = mqttQualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce;
				if (flag8)
				{
					base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(4, 0, null, MqttHelper.BuildIntBytes(data2)).Content);
				}
				else
				{
					bool flag9 = mqttQualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce;
					if (flag9)
					{
						base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(5, 0, null, MqttHelper.BuildIntBytes(data2)).Content);
					}
				}
				bool forbidPublishTopic = session.ForbidPublishTopic;
				if (!forbidPublishTopic)
				{
					MqttServer.OnClientApplicationMessageReceiveDelegate onClientApplicationMessageReceive = this.OnClientApplicationMessageReceive;
					if (onClientApplicationMessageReceive != null)
					{
						onClientApplicationMessageReceive(session, mqttClientApplicationMessage);
					}
					bool flag10 = mqttQualityOfServiceLevel != MqttQualityOfServiceLevel.OnlyTransfer && !mqttClientApplicationMessage.IsCancelPublish;
					if (flag10)
					{
						this.PublishTopicPayload(topic, payload, false);
						bool flag11 = flag5;
						if (flag11)
						{
							this.RetainTopicPayload(topic, mqttClientApplicationMessage);
						}
					}
				}
			}
			else
			{
				bool flag12 = code >> 4 == 3;
				if (flag12)
				{
					string apiTopic = mqttClientApplicationMessage.Topic.Trim(new char[]
					{
						'/'
					});
					MqttRpcApiInfo mqttRpcApiInfo = this.GetMqttRpcApiInfo(apiTopic);
					bool flag13 = mqttRpcApiInfo == null;
					if (flag13)
					{
						MqttServer.OnClientApplicationMessageReceiveDelegate onClientApplicationMessageReceive2 = this.OnClientApplicationMessageReceive;
						if (onClientApplicationMessageReceive2 != null)
						{
							onClientApplicationMessageReceive2(session, mqttClientApplicationMessage);
						}
					}
					else
					{
						DateTime now = DateTime.Now;
						OperateResult<string> operateResult = MqttHelper.HandleObjectMethod(session, mqttClientApplicationMessage, mqttRpcApiInfo);
						double num2 = Math.Round((DateTime.Now - now).TotalSeconds, 5);
						mqttRpcApiInfo.CalledCountAddOne((long)(num2 * 100000.0));
						this.statisticsDict.StatisticsAdd(mqttRpcApiInfo.ApiTopic, 1L);
						ILogNet logNet = base.LogNet;
						if (logNet != null)
						{
							logNet.WriteDebug(this.ToString(), string.Format("{0} RPC: [{1}] Spend:[{2:F2} ms] Count:[{3}] Return:[{4}]", new object[]
							{
								session,
								mqttClientApplicationMessage.Topic,
								num2 * 1000.0,
								mqttRpcApiInfo.CalledCount,
								operateResult.IsSuccess
							}));
						}
						this.ReportOperateResult(session, operateResult);
					}
				}
				else
				{
					bool flag14 = code >> 4 == 8;
					if (flag14)
					{
						this.ReportOperateResult(session, OperateResult.CreateSuccessResult<string>(JArray.FromObject(this.GetAllMqttRpcApiInfo()).ToString()));
					}
					else
					{
						bool flag15 = code >> 4 == 4;
						if (flag15)
						{
							this.PublishTopicPayload(session, "", HslProtocol.PackStringArrayToByte(this.GetAllRetainTopics()));
						}
						else
						{
							bool flag16 = code >> 4 == 6;
							if (flag16)
							{
								long[] array = string.IsNullOrEmpty(mqttClientApplicationMessage.Topic) ? this.LogStatistics.LogStat.GetStatisticsSnapshot() : this.LogStatistics.GetStatisticsSnapshot(mqttClientApplicationMessage.Topic);
								bool flag17 = array == null;
								if (flag17)
								{
									this.ReportOperateResult(session, new OperateResult<string>(string.Format("{0} RPC:{1} has no data or not exist.", session, mqttClientApplicationMessage.Topic)));
								}
								else
								{
									this.ReportOperateResult(session, OperateResult.CreateSuccessResult<string>(array.ToArrayString<long>()));
								}
							}
							else
							{
								bool flag18 = code >> 4 == 5;
								if (flag18)
								{
									object obj = this.keysLock;
									lock (obj)
									{
										bool flag20 = this.retainKeys.ContainsKey(mqttClientApplicationMessage.Topic);
										if (flag20)
										{
											this.PublishTopicPayload(session, mqttClientApplicationMessage.Topic, Encoding.UTF8.GetBytes(this.retainKeys[mqttClientApplicationMessage.Topic].ToJsonString(1)));
										}
										else
										{
											this.ReportOperateResult(session, StringResources.Language.KeyIsNotExist);
										}
									}
								}
							}
						}
					}
				}
			}
		}

		/// <summary>
		/// 将消息进行驻留到内存词典，方便进行其他的功能操作。
		/// </summary>
		/// <param name="topic">消息的主题</param>
		/// <param name="payload">当前的数据负载</param>
		// Token: 0x06000E81 RID: 3713 RVA: 0x00055E8C File Offset: 0x0005408C
		private void RetainTopicPayload(string topic, byte[] payload)
		{
			MqttClientApplicationMessage value = new MqttClientApplicationMessage
			{
				ClientId = "MqttServer",
				QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
				Retain = true,
				Topic = topic,
				UserName = "MqttServer",
				Payload = payload
			};
			object obj = this.keysLock;
			lock (obj)
			{
				bool flag2 = this.retainKeys.ContainsKey(topic);
				if (flag2)
				{
					this.retainKeys[topic] = value;
				}
				else
				{
					this.retainKeys.Add(topic, value);
				}
			}
		}

		/// <summary>
		/// 将消息进行驻留到内存词典，方便进行其他的功能操作。
		/// </summary>
		/// <param name="topic">消息的主题</param>
		/// <param name="message">当前的Mqtt消息</param>
		// Token: 0x06000E82 RID: 3714 RVA: 0x00055F3C File Offset: 0x0005413C
		private void RetainTopicPayload(string topic, MqttClientApplicationMessage message)
		{
			object obj = this.keysLock;
			lock (obj)
			{
				bool flag2 = this.retainKeys.ContainsKey(topic);
				if (flag2)
				{
					this.retainKeys[topic] = message;
				}
				else
				{
					this.retainKeys.Add(topic, message);
				}
			}
		}

		// Token: 0x06000E83 RID: 3715 RVA: 0x00055FB0 File Offset: 0x000541B0
		private void DealWithSubscribe(MqttSession session, byte code, byte[] data)
		{
			int i = 0;
			int data2 = MqttHelper.ExtraIntFromBytes(data, ref i);
			List<string> list = new List<string>();
			while (i < data.Length - 1)
			{
				list.Add(MqttHelper.ExtraSubscribeMsgFromBytes(data, ref i));
			}
			bool flag = i < data.Length;
			if (flag)
			{
				base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(9, 0, MqttHelper.BuildIntBytes(data2), new byte[]
				{
					data[i]
				}).Content);
			}
			else
			{
				base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(9, 0, null, MqttHelper.BuildIntBytes(data2)).Content);
			}
			object obj = this.keysLock;
			lock (obj)
			{
				for (int j = 0; j < list.Count; j++)
				{
					bool flag3 = this.retainKeys.ContainsKey(list[j]);
					if (flag3)
					{
						base.Send(session.MqttSocket, MqttHelper.BuildPublishMqttCommand(list[j], this.retainKeys[list[j]].Payload).Content);
					}
				}
			}
			session.AddSubscribe(list.ToArray());
		}

		// Token: 0x06000E84 RID: 3716 RVA: 0x00056100 File Offset: 0x00054300
		private void DealWithUnSubscribe(MqttSession session, byte code, byte[] data)
		{
			int i = 0;
			int data2 = MqttHelper.ExtraIntFromBytes(data, ref i);
			List<string> list = new List<string>();
			while (i < data.Length)
			{
				list.Add(MqttHelper.ExtraMsgFromBytes(data, ref i));
				i++;
			}
			base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(11, 0, null, MqttHelper.BuildIntBytes(data2)).Content);
			session.RemoveSubscribe(list.ToArray());
		}

		/// <summary>
		/// 向指定的客户端发送主题及负载数据<br />
		/// Sends the topic and payload data to the specified client
		/// </summary>
		/// <param name="session">会话内容</param>
		/// <param name="topic">主题</param>
		/// <param name="payload">消息内容</param>
		// Token: 0x06000E85 RID: 3717 RVA: 0x00056170 File Offset: 0x00054370
		public void PublishTopicPayload(MqttSession session, string topic, byte[] payload)
		{
			OperateResult operateResult = base.Send(session.MqttSocket, MqttHelper.BuildPublishMqttCommand(topic, payload).Content);
			bool flag = !operateResult.IsSuccess;
			if (flag)
			{
				ILogNet logNet = base.LogNet;
				if (logNet != null)
				{
					logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", session) + operateResult.Message);
				}
			}
		}

		/// <summary>
		/// 从服务器向订阅了指定的主题的客户端发送消息，默认消息不驻留<br />
		/// Sends a message from the server to a client that subscribes to the specified topic; the default message does not retain
		/// </summary>
		/// <param name="topic">主题</param>
		/// <param name="payload">消息内容</param>
		/// <param name="retain">指示消息是否驻留</param>
		// Token: 0x06000E86 RID: 3718 RVA: 0x000561D4 File Offset: 0x000543D4
		public void PublishTopicPayload(string topic, byte[] payload, bool retain = true)
		{
			object obj = this.sessionsLock;
			lock (obj)
			{
				for (int i = 0; i < this.mqttSessions.Count; i++)
				{
					bool flag2 = this.mqttSessions[i].IsClientSubscribe(topic) && this.mqttSessions[i].Protocol == "MQTT";
					if (flag2)
					{
						OperateResult operateResult = base.Send(this.mqttSessions[i].MqttSocket, MqttHelper.BuildPublishMqttCommand(topic, payload).Content);
						bool flag3 = !operateResult.IsSuccess;
						if (flag3)
						{
							ILogNet logNet = base.LogNet;
							if (logNet != null)
							{
								logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", this.mqttSessions[i]) + operateResult.Message);
							}
						}
					}
				}
			}
			if (retain)
			{
				this.RetainTopicPayload(topic, payload);
			}
		}

		/// <summary>
		/// 向所有的客户端强制发送主题及负载数据，默认消息不驻留<br />
		/// Send subject and payload data to all clients compulsively, and the default message does not retain
		/// </summary>
		/// <param name="topic">主题</param>
		/// <param name="payload">消息内容</param>
		/// <param name="retain">指示消息是否驻留</param>
		// Token: 0x06000E87 RID: 3719 RVA: 0x000562F0 File Offset: 0x000544F0
		public void PublishAllClientTopicPayload(string topic, byte[] payload, bool retain = false)
		{
			object obj = this.sessionsLock;
			lock (obj)
			{
				for (int i = 0; i < this.mqttSessions.Count; i++)
				{
					bool flag2 = this.mqttSessions[i].Protocol == "MQTT";
					if (flag2)
					{
						OperateResult operateResult = base.Send(this.mqttSessions[i].MqttSocket, MqttHelper.BuildPublishMqttCommand(topic, payload).Content);
						bool flag3 = !operateResult.IsSuccess;
						if (flag3)
						{
							ILogNet logNet = base.LogNet;
							if (logNet != null)
							{
								logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", this.mqttSessions[i]) + operateResult.Message);
							}
						}
					}
				}
			}
			if (retain)
			{
				this.RetainTopicPayload(topic, payload);
			}
		}

		/// <summary>
		/// 向指定的客户端ID强制发送消息，默认消息不驻留<br />
		/// Forces a message to the specified client ID, and the default message does not retain
		/// </summary>
		/// <param name="clientId">指定的客户端ID信息</param>
		/// <param name="topic">主题</param>
		/// <param name="payload">消息内容</param>
		/// <param name="retain">指示消息是否驻留</param>
		// Token: 0x06000E88 RID: 3720 RVA: 0x000563F4 File Offset: 0x000545F4
		public void PublishTopicPayload(string clientId, string topic, byte[] payload, bool retain = false)
		{
			object obj = this.sessionsLock;
			lock (obj)
			{
				for (int i = 0; i < this.mqttSessions.Count; i++)
				{
					bool flag2 = this.mqttSessions[i].ClientId == clientId && this.mqttSessions[i].Protocol == "MQTT";
					if (flag2)
					{
						OperateResult operateResult = base.Send(this.mqttSessions[i].MqttSocket, MqttHelper.BuildPublishMqttCommand(topic, payload).Content);
						bool flag3 = !operateResult.IsSuccess;
						if (flag3)
						{
							ILogNet logNet = base.LogNet;
							if (logNet != null)
							{
								logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", this.mqttSessions[i]) + operateResult.Message);
							}
						}
					}
				}
			}
			if (retain)
			{
				this.RetainTopicPayload(topic, payload);
			}
		}

		/// <summary>
		/// 向客户端发布一个进度报告的信息，仅用于同步网络的时候才支持进度报告，将进度及消息发送给客户端，比如你的服务器需要分成5个部分完成，可以按照百分比提示给客户端当前服务器发生了什么<br />
		/// Publish the information of a progress report to the client. The progress report is only supported when the network is synchronized. 
		/// The progress and the message are sent to the client. For example, your server needs to be divided into 5 parts to complete. 
		/// You can prompt the client according to the percentage. What happened to the server
		/// </summary>
		/// <param name="session">当前的网络会话</param>
		/// <param name="topic">回发客户端的关键数据，可以是百分比字符串，甚至是自定义的任意功能</param>
		/// <param name="payload">数据消息</param>
		// Token: 0x06000E89 RID: 3721 RVA: 0x00056514 File Offset: 0x00054714
		public void ReportProgress(MqttSession session, string topic, string payload)
		{
			bool flag = session.Protocol == "HUSL";
			if (flag)
			{
				payload = (payload ?? string.Empty);
				OperateResult operateResult = base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(15, 0, MqttHelper.BuildSegCommandByString(topic), Encoding.UTF8.GetBytes(payload)).Content);
				bool flag2 = !operateResult.IsSuccess;
				if (flag2)
				{
					ILogNet logNet = base.LogNet;
					if (logNet != null)
					{
						logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", session) + operateResult.Message);
					}
				}
				return;
			}
			throw new Exception("ReportProgress only support sync communication");
		}

		/// <summary>
		/// 向客户端发布一个失败的操作信息，仅用于同步网络的时候反馈失败结果，将错误的信息反馈回客户端，客户端就知道服务器发生了什么，为什么反馈失败。<br />
		/// Publish a failed operation information to the client, which is only used to feed back the failure result when synchronizing the network. 
		/// If the error information is fed back to the client, the client will know what happened to the server and why the feedback failed.
		/// </summary>
		/// <param name="session">当前的网络会话</param>
		/// <param name="message">错误的消息文本信息</param>
		// Token: 0x06000E8A RID: 3722 RVA: 0x000565B8 File Offset: 0x000547B8
		public void ReportOperateResult(MqttSession session, string message)
		{
			this.ReportOperateResult(session, new OperateResult<string>(message));
		}

		/// <summary>
		/// 向客户端发布一个操作结果的信息，仅用于同步网络的时候反馈操作结果，该操作可能成功，可能失败，客户端就知道服务器发生了什么，以及结果如何。<br />
		/// Publish an operation result information to the client, which is only used to feed back the operation result when synchronizing the network. 
		/// The operation may succeed or fail, and the client knows what happened to the server and the result.
		/// </summary>
		/// <param name="session">当前的网络会话</param>
		/// <param name="result">结果对象内容</param>
		// Token: 0x06000E8B RID: 3723 RVA: 0x000565CC File Offset: 0x000547CC
		public void ReportOperateResult(MqttSession session, OperateResult<string> result)
		{
			bool flag = session.Protocol == "HUSL";
			if (flag)
			{
				bool isSuccess = result.IsSuccess;
				if (isSuccess)
				{
					this.PublishTopicPayload(session, result.ErrorCode.ToString(), string.IsNullOrEmpty(result.Content) ? new byte[0] : Encoding.UTF8.GetBytes(result.Content));
				}
				else
				{
					OperateResult operateResult = base.Send(session.MqttSocket, MqttHelper.BuildMqttCommand(0, 0, MqttHelper.BuildSegCommandByString(result.ErrorCode.ToString()), string.IsNullOrEmpty(result.Message) ? new byte[0] : Encoding.UTF8.GetBytes(result.Message)).Content);
					bool flag2 = !operateResult.IsSuccess;
					if (flag2)
					{
						ILogNet logNet = base.LogNet;
						if (logNet != null)
						{
							logNet.WriteError(this.ToString(), string.Format("{0} PublishTopicPayload Failed:", session) + operateResult.Message);
						}
					}
				}
				return;
			}
			throw new Exception("Report Result Message only support sync communication, client is MqttSyncClient");
		}

		/// <summary>
		/// 使用指定的对象来返回网络的API接口，前提是传入的数据为json参数，返回的数据为 <c>OperateResult&lt;string&gt;</c> 数据，详细参照说明<br />
		/// Use the specified object to return the API interface of the network, 
		/// provided that the incoming data is json parameters and the returned data is <c>OperateResult&lt;string&gt;</c> data, 
		/// please refer to the description for details
		/// </summary>
		/// <param name="session">当前的会话内容</param>
		/// <param name="message">客户端发送的消息，其中的payload将会解析为一个json字符串，然后提取参数信息。</param>
		/// <param name="apiObject">当前的对象的内容信息</param>
		// Token: 0x06000E8C RID: 3724 RVA: 0x000566E0 File Offset: 0x000548E0
		public void ReportObjectApiMethod(MqttSession session, MqttClientApplicationMessage message, object apiObject)
		{
			bool flag = session.Protocol == "HUSL";
			if (flag)
			{
				this.ReportOperateResult(session, MqttHelper.HandleObjectMethod(session, message, apiObject));
				return;
			}
			throw new Exception("Report Result Message only support sync communication, client is MqttSyncClient");
		}

		// Token: 0x06000E8D RID: 3725 RVA: 0x00056724 File Offset: 0x00054924
		private MqttRpcApiInfo GetMqttRpcApiInfo(string apiTopic)
		{
			MqttRpcApiInfo result = null;
			object obj = this.rpcApiLock;
			lock (obj)
			{
				bool flag2 = this.apiTopicServiceDict.ContainsKey(apiTopic);
				if (flag2)
				{
					result = this.apiTopicServiceDict[apiTopic];
				}
			}
			return result;
		}

		/// <summary>
		/// 获取当前所有注册的RPC接口信息，将返回一个数据列表。<br />
		/// Get all currently registered RPC interface information, and a data list will be returned.
		/// </summary>
		/// <returns>信息列表</returns>
		// Token: 0x06000E8E RID: 3726 RVA: 0x0005678C File Offset: 0x0005498C
		public MqttRpcApiInfo[] GetAllMqttRpcApiInfo()
		{
			MqttRpcApiInfo[] result = null;
			object obj = this.rpcApiLock;
			lock (obj)
			{
				result = Enumerable.ToArray<MqttRpcApiInfo>(this.apiTopicServiceDict.Values);
			}
			return result;
		}

		/// <summary>
		/// 注册一个RPC的服务接口，可以指定当前的控制器名称，以及提供RPC服务的原始对象，指定统一的权限控制。<br />
		/// Register an RPC service interface, you can specify the current controller name, 
		/// and the original object that provides the RPC service, Specify unified access control
		/// </summary>
		/// <param name="api">前置的接口信息，可以理解为MVC模式的控制器</param>
		/// <param name="obj">原始对象信息</param>
		/// <param name="permissionAttribute">统一的权限访问配置，将会覆盖单个方法的权限控制。</param>
		// Token: 0x06000E8F RID: 3727 RVA: 0x000567E4 File Offset: 0x000549E4
		public void RegisterMqttRpcApi(string api, object obj, HslMqttPermissionAttribute permissionAttribute)
		{
			object obj2 = this.rpcApiLock;
			lock (obj2)
			{
				foreach (MqttRpcApiInfo mqttRpcApiInfo in MqttHelper.GetSyncServicesApiInformationFromObject(api, obj, permissionAttribute))
				{
					this.apiTopicServiceDict.Add(mqttRpcApiInfo.ApiTopic, mqttRpcApiInfo);
				}
			}
		}

		/// <summary>
		/// 注册一个RPC的服务接口，可以指定当前的控制器名称，以及提供RPC服务的原始对象<br />
		/// Register an RPC service interface, you can specify the current controller name, 
		/// and the original object that provides the RPC service
		/// </summary>
		/// <param name="api">前置的接口信息，可以理解为MVC模式的控制器</param>
		/// <param name="obj">原始对象信息</param>
		// Token: 0x06000E90 RID: 3728 RVA: 0x00056878 File Offset: 0x00054A78
		public void RegisterMqttRpcApi(string api, object obj)
		{
			object obj2 = this.rpcApiLock;
			lock (obj2)
			{
				foreach (MqttRpcApiInfo mqttRpcApiInfo in MqttHelper.GetSyncServicesApiInformationFromObject(api, obj, null))
				{
					this.apiTopicServiceDict.Add(mqttRpcApiInfo.ApiTopic, mqttRpcApiInfo);
				}
			}
		}

		/// <inheritdoc cref="M:HslCommunication.MQTT.MqttServer.RegisterMqttRpcApi(System.String,System.Object)" />
		// Token: 0x06000E91 RID: 3729 RVA: 0x0005690C File Offset: 0x00054B0C
		public void RegisterMqttRpcApi(object obj)
		{
			object obj2 = this.rpcApiLock;
			lock (obj2)
			{
				foreach (MqttRpcApiInfo mqttRpcApiInfo in MqttHelper.GetSyncServicesApiInformationFromObject(obj))
				{
					this.apiTopicServiceDict.Add(mqttRpcApiInfo.ApiTopic, mqttRpcApiInfo);
				}
			}
		}

		/// <summary>
		/// 启动文件服务功能，协议头为FILE，需要指定服务器存储的文件路径<br />
		/// Start the file service function, the protocol header is FILE, you need to specify the file path stored by the server
		/// </summary>
		/// <param name="filePath">文件的存储路径</param>
		// Token: 0x06000E92 RID: 3730 RVA: 0x000569A0 File Offset: 0x00054BA0
		public void UseFileServer(string filePath)
		{
			this.filesDirectoryPath = filePath;
			this.fileServerEnabled = true;
			this.CheckFolderAndCreate();
		}

		/// <summary>
		/// 关闭文件服务功能
		/// </summary>
		// Token: 0x06000E93 RID: 3731 RVA: 0x000569B8 File Offset: 0x00054BB8
		public void CloseFileServer()
		{
			this.fileServerEnabled = false;
		}

		/// <summary>
		/// 获取当前的针对文件夹的文件管理容器的数量<br />
		/// Get the current number of file management containers for the folder
		/// </summary>
		// Token: 0x06000E94 RID: 3732 RVA: 0x000569C2 File Offset: 0x00054BC2
		[HslMqttApi(Description = "Get the current number of file management containers for the folder")]
		public int GroupFileContainerCount()
		{
			return this.m_dictionary_group_marks.Count;
		}

		/// <summary>
		/// 获取当前实时的文件上传下载的监控信息，操作的客户端信息，文件分类，文件名，上传或下载的速度等<br />
		/// Obtain current real-time file upload and download monitoring information, operating client information, file classification, file name, upload or download speed, etc.
		/// </summary>
		/// <returns>文件的监控信息</returns>
		// Token: 0x06000E95 RID: 3733 RVA: 0x000569CF File Offset: 0x00054BCF
		[HslMqttApi(Description = "Obtain current real-time file upload and download monitoring information, operating client information, file classification, file name, upload or download speed, etc.")]
		public MqttFileMonitorItem[] GetMonitorItemsSnapShoot()
		{
			return this.fileMonitor.GetMonitorItemsSnapShoot();
		}

		/// <summary>
		/// 当客户端进行文件操作时，校验客户端合法性的事件，操作码具体查看<seealso cref="T:HslCommunication.MQTT.MqttControlMessage" />的常量值<br />
		/// When client performing file operations, it is an event to verify the legitimacy of the client. For the operation code, check the constant value of <seealso cref="T:HslCommunication.MQTT.MqttControlMessage" />
		/// </summary>
		// Token: 0x14000015 RID: 21
		// (add) Token: 0x06000E96 RID: 3734 RVA: 0x000569DC File Offset: 0x00054BDC
		// (remove) Token: 0x06000E97 RID: 3735 RVA: 0x00056A14 File Offset: 0x00054C14
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.FileOperateVerificationDelegate FileOperateVerification;

		// Token: 0x06000E98 RID: 3736 RVA: 0x00056A4C File Offset: 0x00054C4C
		private bool CheckPathAndFilenameLegal(string input)
		{
			return input.Contains(":") || input.Contains("?") || input.Contains("*") || input.Contains("/") || input.Contains("\\") || input.Contains("\"") || input.Contains("<") || input.Contains(">") || input.Contains("|");
		}

		// Token: 0x06000E99 RID: 3737 RVA: 0x00056AD4 File Offset: 0x00054CD4
		[DebuggerStepThrough]
		private Task HandleFileMessageAsync(MqttSession session)
		{
			MqttServer.<HandleFileMessageAsync>d__46 <HandleFileMessageAsync>d__ = new MqttServer.<HandleFileMessageAsync>d__46();
			<HandleFileMessageAsync>d__.<>t__builder = AsyncTaskMethodBuilder.Create();
			<HandleFileMessageAsync>d__.<>4__this = this;
			<HandleFileMessageAsync>d__.session = session;
			<HandleFileMessageAsync>d__.<>1__state = -1;
			<HandleFileMessageAsync>d__.<>t__builder.Start<MqttServer.<HandleFileMessageAsync>d__46>(ref <HandleFileMessageAsync>d__);
			return <HandleFileMessageAsync>d__.<>t__builder.Task;
		}

		/// <summary>
		/// 从套接字接收文件并保存，更新文件列表
		/// </summary>
		/// <param name="session">当前的会话信息</param>
		/// <param name="info">保存的信息</param>
		/// <param name="reportProgress">当前的委托信息</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E9A RID: 3738 RVA: 0x00056B20 File Offset: 0x00054D20
		[DebuggerStepThrough]
		private Task<OperateResult<FileBaseInfo>> ReceiveMqttFileAndUpdateGroupAsync(MqttSession session, FileInfo info, Action<long, long> reportProgress)
		{
			MqttServer.<ReceiveMqttFileAndUpdateGroupAsync>d__47 <ReceiveMqttFileAndUpdateGroupAsync>d__ = new MqttServer.<ReceiveMqttFileAndUpdateGroupAsync>d__47();
			<ReceiveMqttFileAndUpdateGroupAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult<FileBaseInfo>>.Create();
			<ReceiveMqttFileAndUpdateGroupAsync>d__.<>4__this = this;
			<ReceiveMqttFileAndUpdateGroupAsync>d__.session = session;
			<ReceiveMqttFileAndUpdateGroupAsync>d__.info = info;
			<ReceiveMqttFileAndUpdateGroupAsync>d__.reportProgress = reportProgress;
			<ReceiveMqttFileAndUpdateGroupAsync>d__.<>1__state = -1;
			<ReceiveMqttFileAndUpdateGroupAsync>d__.<>t__builder.Start<MqttServer.<ReceiveMqttFileAndUpdateGroupAsync>d__47>(ref <ReceiveMqttFileAndUpdateGroupAsync>d__);
			return <ReceiveMqttFileAndUpdateGroupAsync>d__.<>t__builder.Task;
		}

		/// <summary>
		/// 返回相对路径的名称
		/// </summary>
		/// <param name="groups">文件的分类路径信息</param>
		/// <param name="fileName">文件名</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E9B RID: 3739 RVA: 0x00056B7C File Offset: 0x00054D7C
		private string GetRelativeFileName(string[] groups, string fileName)
		{
			string path = "";
			for (int i = 0; i < groups.Length; i++)
			{
				bool flag = !string.IsNullOrEmpty(groups[i]);
				if (flag)
				{
					path = Path.Combine(path, groups[i]);
				}
			}
			return Path.Combine(path, fileName);
		}

		/// <summary>
		/// 返回服务器的绝对路径，包含根目录的信息  [Root Dir][A][B][C]... 信息
		/// </summary>
		/// <param name="groups">文件的路径分类信息</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E9C RID: 3740 RVA: 0x00056BC8 File Offset: 0x00054DC8
		private string ReturnAbsoluteFilePath(string[] groups)
		{
			return Path.Combine(this.filesDirectoryPath, Path.Combine(groups));
		}

		/// <summary>
		/// 返回服务器的绝对路径，包含根目录的信息  [Root Dir][A][B][C]...[FileName] 信息
		/// </summary>
		/// <param name="groups">路径分类信息</param>
		/// <param name="fileName">文件名</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E9D RID: 3741 RVA: 0x00056BEC File Offset: 0x00054DEC
		protected string ReturnAbsoluteFileName(string[] groups, string fileName)
		{
			return Path.Combine(this.ReturnAbsoluteFilePath(groups), fileName);
		}

		/// <summary>
		/// 根据文件的显示名称转化为真实存储的名称，例如 123.txt 获取到在文件服务器里映射的文件名称，例如返回 b35a11ec533147ca80c7f7d1713f015b7909
		/// </summary>
		/// <param name="groups">文件的分类信息</param>
		/// <param name="fileName">文件显示名称</param>
		/// <returns>是否成功的结果对象</returns>
		// Token: 0x06000E9E RID: 3742 RVA: 0x00056C0C File Offset: 0x00054E0C
		private string TransformFactFileName(string[] groups, string fileName)
		{
			string filePath = this.ReturnAbsoluteFilePath(groups);
			GroupFileContainer groupFromFilePath = this.GetGroupFromFilePath(filePath);
			return groupFromFilePath.GetCurrentFileMappingName(fileName);
		}

		/// <summary>
		/// 获取当前目录的文件列表管理容器，如果没有会自动创建，通过该容器可以实现对当前目录的文件进行访问<br />
		/// Get the file list management container of the current directory. If not, it will be created automatically. 
		/// Through this container, you can access files in the current directory.
		/// </summary>
		/// <param name="filePath">路径信息</param>
		/// <returns>文件管理容器信息</returns>
		// Token: 0x06000E9F RID: 3743 RVA: 0x00056C38 File Offset: 0x00054E38
		private GroupFileContainer GetGroupFromFilePath(string filePath)
		{
			filePath = filePath.ToUpper();
			this.group_marks_lock.Enter();
			bool flag = this.m_dictionary_group_marks.ContainsKey(filePath);
			GroupFileContainer groupFileContainer;
			if (flag)
			{
				groupFileContainer = this.m_dictionary_group_marks[filePath];
			}
			else
			{
				groupFileContainer = new GroupFileContainer(base.LogNet, filePath);
				this.m_dictionary_group_marks.Add(filePath, groupFileContainer);
			}
			this.group_marks_lock.Leave();
			return groupFileContainer;
		}

		/// <summary>
		/// 获取文件夹的所有文件夹列表
		/// </summary>
		/// <param name="groups">分类信息</param>
		/// <returns>文件夹列表</returns>
		// Token: 0x06000EA0 RID: 3744 RVA: 0x00056CAC File Offset: 0x00054EAC
		private string[] GetDirectories(string[] groups)
		{
			bool flag = string.IsNullOrEmpty(this.filesDirectoryPath);
			string[] result;
			if (flag)
			{
				result = new string[0];
			}
			else
			{
				string path = this.ReturnAbsoluteFilePath(groups);
				bool flag2 = !Directory.Exists(path);
				if (flag2)
				{
					result = new string[0];
				}
				else
				{
					result = Directory.GetDirectories(path);
				}
			}
			return result;
		}

		/// <summary>
		/// 获取当前文件的读写锁，如果没有会自动创建，文件名应该是guid文件名，例如 b35a11ec533147ca80c7f7d1713f015b7909<br />
		/// Acquire the read-write lock of the current file. If not, it will be created automatically. 
		/// The file name should be the guid file name, for example, b35a11ec533147ca80c7f7d1713f015b7909
		/// </summary>
		/// <param name="fileName">完整的文件路径</param>
		/// <returns>返回携带文件信息的读写锁</returns>
		// Token: 0x06000EA1 RID: 3745 RVA: 0x00056CFC File Offset: 0x00054EFC
		private FileMarkId GetFileMarksFromDictionaryWithFileName(string fileName)
		{
			object obj = this.dictHybirdLock;
			FileMarkId fileMarkId;
			lock (obj)
			{
				bool flag2 = this.dictionaryFilesMarks.ContainsKey(fileName);
				if (flag2)
				{
					fileMarkId = this.dictionaryFilesMarks[fileName];
				}
				else
				{
					fileMarkId = new FileMarkId(base.LogNet, fileName);
					this.dictionaryFilesMarks.Add(fileName, fileMarkId);
				}
			}
			return fileMarkId;
		}

		/// <summary>
		/// 检查文件夹是否存在，不存在就创建
		/// </summary>
		// Token: 0x06000EA2 RID: 3746 RVA: 0x00056D80 File Offset: 0x00054F80
		private void CheckFolderAndCreate()
		{
			bool flag = !Directory.Exists(this.filesDirectoryPath);
			if (flag)
			{
				Directory.CreateDirectory(this.filesDirectoryPath);
			}
		}

		/// <summary>
		/// 删除已经存在的文件信息，文件的名称需要是guid名称，例如 b35a11ec533147ca80c7f7d1713f015b7909
		/// </summary>
		/// <param name="path">文件的路径</param>
		/// <param name="fileName">文件的guid名称，例如 b35a11ec533147ca80c7f7d1713f015b7909</param>
		// Token: 0x06000EA3 RID: 3747 RVA: 0x00056DAC File Offset: 0x00054FAC
		private void DeleteExsistingFile(string path, string fileName)
		{
			this.DeleteExsistingFile(path, new List<string>
			{
				fileName
			});
		}

		/// <summary>
		/// 删除已经存在的文件信息，文件的名称需要是guid名称，例如 b35a11ec533147ca80c7f7d1713f015b7909
		/// </summary>
		/// <param name="path">文件的路径</param>
		/// <param name="fileNames">文件的guid名称，例如 b35a11ec533147ca80c7f7d1713f015b7909</param>
		// Token: 0x06000EA4 RID: 3748 RVA: 0x00056DC4 File Offset: 0x00054FC4
		private void DeleteExsistingFile(string path, List<string> fileNames)
		{
			foreach (string text in fileNames)
			{
				bool flag = !string.IsNullOrEmpty(text);
				if (flag)
				{
					string fileUltimatePath = Path.Combine(path, text);
					FileMarkId fileMarksFromDictionaryWithFileName = this.GetFileMarksFromDictionaryWithFileName(text);
					fileMarksFromDictionaryWithFileName.AddOperation(delegate
					{
						bool flag2 = !this.DeleteFileByName(fileUltimatePath);
						if (flag2)
						{
							ILogNet logNet = this.LogNet;
							if (logNet != null)
							{
								logNet.WriteInfo(this.ToString(), StringResources.Language.FileDeleteFailed + fileUltimatePath);
							}
						}
						else
						{
							ILogNet logNet2 = this.LogNet;
							if (logNet2 != null)
							{
								logNet2.WriteInfo(this.ToString(), StringResources.Language.FileDeleteSuccess + fileUltimatePath);
							}
						}
					});
				}
			}
		}

		/// <summary>
		/// 文件变化的事件，当文件上传的时候，文件下载的时候，文件被删除的时候触发。<br />
		/// The file change event is triggered when the file is uploaded, when the file is downloaded, or when the file is deleted.
		/// </summary>
		// Token: 0x14000016 RID: 22
		// (add) Token: 0x06000EA5 RID: 3749 RVA: 0x00056E58 File Offset: 0x00055058
		// (remove) Token: 0x06000EA6 RID: 3750 RVA: 0x00056E90 File Offset: 0x00055090
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.FileChangedDelegate OnFileChangedEvent;

		// Token: 0x06000EA7 RID: 3751 RVA: 0x00056EC8 File Offset: 0x000550C8
		private void AddMqttSession(MqttSession session)
		{
			object obj = this.sessionsLock;
			lock (obj)
			{
				this.mqttSessions.Add(session);
			}
			ILogNet logNet = base.LogNet;
			if (logNet != null)
			{
				logNet.WriteDebug(this.ToString(), string.Format("{0} Online", session));
			}
		}

		/// <summary>
		/// 让MQTT客户端正常下线，调用本方法即可自由控制会话客户端强制下线操作。
		/// </summary>
		/// <param name="session">当前的会话信息</param>
		/// <param name="reason">当前下线的原因，如果没有，代表正常下线</param>
		// Token: 0x06000EA8 RID: 3752 RVA: 0x00056F38 File Offset: 0x00055138
		public void RemoveAndCloseSession(MqttSession session, string reason)
		{
			object obj = this.sessionsLock;
			lock (obj)
			{
				this.mqttSessions.Remove(session);
			}
			Socket mqttSocket = session.MqttSocket;
			if (mqttSocket != null)
			{
				mqttSocket.Close();
			}
			ILogNet logNet = base.LogNet;
			if (logNet != null)
			{
				logNet.WriteDebug(this.ToString(), string.Format("{0} Offline {1}", session, reason));
			}
			bool flag2 = session.Protocol == "MQTT";
			if (flag2)
			{
				MqttServer.OnClientConnectedDelegate onClientDisConnected = this.OnClientDisConnected;
				if (onClientDisConnected != null)
				{
					onClientDisConnected(session);
				}
			}
		}

		/// <summary>
		/// 当收到客户端发来的<see cref="T:HslCommunication.MQTT.MqttClientApplicationMessage" />消息时触发<br />
		/// Triggered when a <see cref="T:HslCommunication.MQTT.MqttClientApplicationMessage" /> message is received from the client
		///             </summary>
		// Token: 0x14000017 RID: 23
		// (add) Token: 0x06000EA9 RID: 3753 RVA: 0x00056FE4 File Offset: 0x000551E4
		// (remove) Token: 0x06000EAA RID: 3754 RVA: 0x0005701C File Offset: 0x0005521C
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.OnClientApplicationMessageReceiveDelegate OnClientApplicationMessageReceive;

		/// <summary>
		/// Mqtt的客户端连接上来时触发<br />
		/// Triggered when Mqtt client connects
		/// </summary>
		// Token: 0x14000018 RID: 24
		// (add) Token: 0x06000EAB RID: 3755 RVA: 0x00057054 File Offset: 0x00055254
		// (remove) Token: 0x06000EAC RID: 3756 RVA: 0x0005708C File Offset: 0x0005528C
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.OnClientConnectedDelegate OnClientConnected;

		/// <summary>
		/// Mqtt的客户端下线时触发<br />
		/// Triggered when Mqtt client connects
		/// </summary>
		// Token: 0x14000019 RID: 25
		// (add) Token: 0x06000EAD RID: 3757 RVA: 0x000570C4 File Offset: 0x000552C4
		// (remove) Token: 0x06000EAE RID: 3758 RVA: 0x000570FC File Offset: 0x000552FC
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.OnClientConnectedDelegate OnClientDisConnected;

		/// <summary>
		/// 当客户端连接时，触发的验证事件<br />
		/// Validation event triggered when the client connects
		/// </summary>
		// Token: 0x1400001A RID: 26
		// (add) Token: 0x06000EAF RID: 3759 RVA: 0x00057134 File Offset: 0x00055334
		// (remove) Token: 0x06000EB0 RID: 3760 RVA: 0x0005716C File Offset: 0x0005536C
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public event MqttServer.ClientVerificationDelegate ClientVerification;

		/// <inheritdoc cref="P:HslCommunication.Enthernet.HttpServer.LogStatistics" />
		// Token: 0x17000220 RID: 544
		// (get) Token: 0x06000EB1 RID: 3761 RVA: 0x000571A1 File Offset: 0x000553A1
		public LogStatisticsDict LogStatistics
		{
			get
			{
				return this.statisticsDict;
			}
		}

		/// <summary>
		/// 获取当前的在线的客户端数量<br />
		/// Gets the number of clients currently online
		/// </summary>
		// Token: 0x17000221 RID: 545
		// (get) Token: 0x06000EB2 RID: 3762 RVA: 0x000571A9 File Offset: 0x000553A9
		public int OnlineCount
		{
			get
			{
				return this.mqttSessions.Count;
			}
		}

		/// <summary>
		/// 获得当前所有的在线的MQTT客户端信息，包括异步的客户端及同步请求的客户端。<br />
		/// Obtain all current online MQTT client information, including asynchronous client and synchronous request client.
		/// </summary>
		// Token: 0x17000222 RID: 546
		// (get) Token: 0x06000EB3 RID: 3763 RVA: 0x000571B8 File Offset: 0x000553B8
		public MqttSession[] OnlineSessions
		{
			get
			{
				MqttSession[] result = null;
				object obj = this.sessionsLock;
				lock (obj)
				{
					result = this.mqttSessions.ToArray();
				}
				return result;
			}
		}

		/// <summary>
		/// 获得当前异步客户端在线的MQTT客户端信息。<br />
		/// Get the MQTT client information of the current asynchronous client online.
		/// </summary>
		// Token: 0x17000223 RID: 547
		// (get) Token: 0x06000EB4 RID: 3764 RVA: 0x00057208 File Offset: 0x00055408
		public MqttSession[] MqttOnlineSessions
		{
			get
			{
				MqttSession[] result = null;
				object obj = this.sessionsLock;
				lock (obj)
				{
					result = Enumerable.ToArray<MqttSession>(Enumerable.Where<MqttSession>(this.mqttSessions, (MqttSession m) => m.Protocol == "MQTT"));
				}
				return result;
			}
		}

		/// <summary>
		/// 获得当前同步客户端在线的MQTT客户端信息，如果客户端是短连接，将难以捕获在在线信息。<br />
		/// Obtain the MQTT client information of the current synchronization client online. If the client is a short connection, it will be difficult to capture the online information. <br />
		/// </summary>
		// Token: 0x17000224 RID: 548
		// (get) Token: 0x06000EB5 RID: 3765 RVA: 0x0005727C File Offset: 0x0005547C
		public MqttSession[] SyncOnlineSessions
		{
			get
			{
				MqttSession[] result = null;
				object obj = this.sessionsLock;
				lock (obj)
				{
					result = Enumerable.ToArray<MqttSession>(Enumerable.Where<MqttSession>(this.mqttSessions, (MqttSession m) => m.Protocol == "HUSL"));
				}
				return result;
			}
		}

		/// <summary>
		/// 删除服务器里的指定主题的驻留消息。<br />
		/// Delete the resident message of the specified topic in the server.
		/// </summary>
		/// <param name="topic">等待删除的主题关键字</param>
		// Token: 0x06000EB6 RID: 3766 RVA: 0x000572F0 File Offset: 0x000554F0
		public void DeleteRetainTopic(string topic)
		{
			object obj = this.keysLock;
			lock (obj)
			{
				bool flag2 = this.retainKeys.ContainsKey(topic);
				if (flag2)
				{
					this.retainKeys.Remove(topic);
				}
			}
		}

		/// <summary>
		/// 获取所有的驻留的消息的主题，如果消息发布的时候没有使用Retain属性，就无法通过本方法查到<br />
		/// Get the subject of all resident messages. If the Retain attribute is not used when the message is published, it cannot be found by this method
		/// </summary>
		/// <returns>主题的数组</returns>
		// Token: 0x06000EB7 RID: 3767 RVA: 0x00057350 File Offset: 0x00055550
		public string[] GetAllRetainTopics()
		{
			string[] result = null;
			object obj = this.keysLock;
			lock (obj)
			{
				result = Enumerable.ToArray<string>(Enumerable.Select<KeyValuePair<string, MqttClientApplicationMessage>, string>(this.retainKeys, (KeyValuePair<string, MqttClientApplicationMessage> m) => m.Key));
			}
			return result;
		}

		/// <inheritdoc />
		// Token: 0x06000EB8 RID: 3768 RVA: 0x000573C8 File Offset: 0x000555C8
		public override string ToString()
		{
			return string.Format("MqttServer[{0}]", base.Port);
		}

		// Token: 0x040003F2 RID: 1010
		private Dictionary<string, MqttRpcApiInfo> apiTopicServiceDict;

		// Token: 0x040003F3 RID: 1011
		private object rpcApiLock;

		// Token: 0x040003F4 RID: 1012
		private readonly Dictionary<string, FileMarkId> dictionaryFilesMarks;

		// Token: 0x040003F5 RID: 1013
		private readonly object dictHybirdLock;

		// Token: 0x040003F6 RID: 1014
		private string filesDirectoryPath = null;

		// Token: 0x040003F7 RID: 1015
		private bool fileServerEnabled = false;

		// Token: 0x040003F8 RID: 1016
		private Dictionary<string, GroupFileContainer> m_dictionary_group_marks = new Dictionary<string, GroupFileContainer>();

		// Token: 0x040003F9 RID: 1017
		private SimpleHybirdLock group_marks_lock = new SimpleHybirdLock();

		// Token: 0x040003FA RID: 1018
		private MqttFileMonitor fileMonitor = new MqttFileMonitor();

		// Token: 0x04000401 RID: 1025
		private readonly Dictionary<string, MqttClientApplicationMessage> retainKeys;

		// Token: 0x04000402 RID: 1026
		private readonly object keysLock;

		// Token: 0x04000403 RID: 1027
		private readonly List<MqttSession> mqttSessions = new List<MqttSession>();

		// Token: 0x04000404 RID: 1028
		private readonly object sessionsLock = new object();

		// Token: 0x04000405 RID: 1029
		private Timer timerHeart;

		// Token: 0x04000406 RID: 1030
		private LogStatisticsDict statisticsDict;

		/// <summary>
		/// 当客户端进行文件操作时，校验客户端合法性的委托，操作码具体查看<seealso cref="T:HslCommunication.MQTT.MqttControlMessage" />的常量值<br />
		/// When client performing file operations, verify the legitimacy of the client, and check the constant value of <seealso cref="T:HslCommunication.MQTT.MqttControlMessage" /> for the operation code.
		/// </summary>
		/// <param name="session">会话状态</param>
		/// <param name="code">操作码</param>
		/// <param name="groups">分类信息</param>
		/// <param name="fileNames">文件名</param>
		/// <returns>是否成功</returns>
		// Token: 0x02000445 RID: 1093
		// (Invoke) Token: 0x06002956 RID: 10582
		public delegate OperateResult FileOperateVerificationDelegate(MqttSession session, byte code, string[] groups, string[] fileNames);

		/// <summary>
		/// 文件变化的委托信息
		/// </summary>
		/// <param name="session">当前的会话信息，包含用户的基本信息</param>
		/// <param name="operateInfo">当前的文件操作信息，具体指示上传，下载，删除操作</param>
		// Token: 0x02000446 RID: 1094
		// (Invoke) Token: 0x0600295A RID: 10586
		public delegate void FileChangedDelegate(MqttSession session, MqttFileOperateInfo operateInfo);

		/// <summary>
		/// Mqtt的消息收到委托
		/// </summary>
		/// <param name="session">当前会话的内容</param>
		/// <param name="message">Mqtt的消息</param>
		// Token: 0x02000447 RID: 1095
		// (Invoke) Token: 0x0600295E RID: 10590
		public delegate void OnClientApplicationMessageReceiveDelegate(MqttSession session, MqttClientApplicationMessage message);

		/// <summary>
		/// 当前mqtt客户端连接上服务器的事件委托
		/// </summary>
		/// <param name="session">当前的会话对象</param>
		// Token: 0x02000448 RID: 1096
		// (Invoke) Token: 0x06002962 RID: 10594
		public delegate void OnClientConnectedDelegate(MqttSession session);

		/// <summary>
		/// 验证的委托
		/// </summary>
		/// <param name="mqttSession">当前的MQTT的会话内容</param>
		/// <param name="clientId">客户端的id</param>
		/// <param name="userName">用户名</param>
		/// <param name="passwrod">密码</param>
		/// <returns>0则是通过，否则，就是连接失败</returns>
		// Token: 0x02000449 RID: 1097
		// (Invoke) Token: 0x06002966 RID: 10598
		public delegate int ClientVerificationDelegate(MqttSession mqttSession, string clientId, string userName, string passwrod);
	}
}
